TurboCalc3 Šopyright 1993-94 by Michael Friedrich. All Rights Reserved This document must not be copied, modified or released without my written permission. It is part of TurboCalc3.0. 1. TCLIB - TurboCalc Library ============================ Starting with version 3 of TurboCalc you have the possibility to enhance the internal functions, macros, objectclasses and other things by external routines. This way you, the user, can add personal features to TurboCalc to facilitate your work. This is done by providing external files with specific routines. The creation of such a file, called 'TCLib', will be discussed in the following text. IMPORTANT: TO CREATE A TCLIB YOU SHOULD BE FAMILIAR WITH PROGRAMMING THE AMIGA. FOR USING TURBOCALC IT IS NOT NECESSARY TO READ OR UNDERSTAND THIS MANUAL. Creating TCLibs is a very advanced feature of TurboCalc Up to now, there are the following types of TCLibs: * Filerequester * Objects * crypting-routines * External functions * External macro-commands 1.1. What is a TCLibs? ---------------------- A TCLib is an (almost) normal executable AmigaDOS-file and might thus be created with most of the popular compilers or assemblers. Logically, each TCLib can be divided in three parts: 1) The first part is the TCLib-header. It contains some useful information about the TCLib and allows TurboCalc to verify that this is really a TCLib. This prevents a system crash due to improper use. 2) This header is finished with a list of all implemented routines, which enables TurboCalc to find and call the 'real routines'. (This part is often included in 1, and both are called header) 3) Finally, the real routines are placed here. The header *must* be the first thing in your executable file. If you are using a compiler to create the TCLib you have to ensure that. To do this, all the startup-code must be removed. Further hints should be found in the description of 'creating libraries' in your compiler-documentation, as creating (normal) amigalibraries is much the same as creating TCLibs. Annotation: As the best way to implement such a TCLib is assembler and TurboCalc is completely written in assembler, all the structures and descriptions in this documentation will be in that language. 2. TCLib-Structure ================== 2.1. The Header --------------- The header looks like this: In the first part, you will find some values that allow TurboCalc to identify this TCLib and determine the type. The second part consists of a list of pointers for the respective routines. The first four ones are common to all TCLib-types. They are used on startup & when quitting TurboCalc. (See short description in the structure below). The others are type-specific and will be explained in the respective chapters below. STRUCTURE TCLib,0 LONG tclib_header ; moveq #-13,d0 or $70F34E75 ; rts ; if user tries to start this file! LONG tclib_id ; TCLIB_ID ('TCLB') LONG tclib_subid ; one of the TCLIB_SUBID's declared above WORD tclib_version WORD tclib_revision LONG tclib_name ; *text with short description of this lib LONG tclib_ver ; *ver_text LONG tclib_author ; *text with your name LONG tclib_flags ; reserved, set to 0.l for now LONG lib_reserved1 ; dito LONG lib_reserved2 ; dito ***** end of header part1 LONG tclib_init ;INIT: routine is called on startup, return one of: ; 0: if installed correctly ; 1: can't use: remove - try to load next time ; -1: impossible to use: remove & don't try ; to load this lib again LONG tclib_exit ;END: routine is called before TurboCalc ends ; free all allocated mem & other resources LONG tclib_flush ;FLUSH: routine is called when TurboCalc runs ; runs short of memory. ; lib is asked to free (temporarily) unused ; memory (not used up to now, simply set to 0.l) LONG tclib_method ; Global routine for all purposes, called with ; method (what shall be done?) and data. ; Isn't currently used. (Simply set to 0) LABEL tclib_rout1 ; Here the type-specific routines start, they are ; defined in the type-specific description below. LABEL TCLib_SIZEOF The rest of this structure contains pointers to the used routines and is thus depending on the type of TCLib. Parameters are passed in registers (as usually in assembler), see 'Calling Conventions' below. 2.2 FileRequester-TCLib ----------------------- This TCLibs allows to change the TurboCalc-filerequester and to replace it by a new one. You only need one routine asking for a filename. Thus the (rest of the) TCLib-structure looks like this: STRUCTURE TCLib_filereq,TCLib_SIZEOF LONG libfr_filereq ; open window & ask for filename ; error=filereq(filename, title_text, screen, pattern, flags) ; a0 a1 a2 a3 d0 ; para: a0: *filename (200 chars reserved, both for old and ; for new filename, if returning d0=0) ; a1: *title_text ; a2: *screen (or 0.l for workbench) ; a3: *pattern ; d0: flags (bit0: save, bit1:drawer_only) ; (drawer_only isn't needed up to now!) ; return: d0: 0=ok (filename is changed) ; 1=abort ; -1=serious error (e.g. no mem) ; (in this case a simple string- ; filerequester will appear) LABEL libfr_SIZEOF Annotation: In a0 your routines gets a pointer to a buffer with (at least) 200 chars containing the current filename. If the user selected a new filename and you're returning ok (d0=0), the buffer should be changed accordingly (i.e. the buffer should be filled with the new filename, complete path & name). All the other information might and should!) be used for better handling. 2.3 Crypt-TCLib --------------- This TCLib is used to encrypt and decrypt the sheets when saving/loading and the respective option is set (in ). Three routines are needed, one for setting the password and the other two for encryption & decryption. STRUCTURE TCLib_crypt,TCLib_SIZEOF LONG libcrypt_password ; set password for en/decrypting ; para: a0= *string, null-terminated ; either copy this string to your one buffer or ; (even better) use an algorithm to calculate ; real key (e.g. MD5 or CRC) LONG libcrypt_encrypt ; encrypt block ; para: a0= *block ; d0= length of block (in bytes) LONG libcrypt_decrypt ; decrypt block ; para: a0= *block ; d0= length of block (in bytes) LABEL libcrypt_SIZEOF For every loading/saving the decryption/encryption-routines are called multiple times (once for each block). Block-size may vary (the first block is shorter (header missing) and the last block might be shorter as well) You should be prepared for this (e.g. by storing temporary data). You can rely on i) libcrypt_password is called once directly before the en-/decryption. ii) calls to _encrypt and _decrypt aren't mixed. iii) buffer is longword-aligned (i.e. buffer&3=0) and (except for the last block) length is a multiple of 4. Thus it is possible to use (long)word commands. (As the size of a TurboCalc-sheet isn't longword aligned, the last block might have an odd size. Either you handle this or, if you are lazy, you simple align the length to the next lower (long)word-boundary, keeping the last three bytes unchanged.) For your information, loading works like this: i) libcrypt_password is called to set the password ii) first block is loaded in memory and libcrypt_decrypt is called iii) this is repeated until the complete file has been read. 2.4. ObjectClass-TCLib ---------------------- This is the most complex TCLib (up to now). It is used to add new objectclasses allowing TurboCalc to handle and display various objects without an hardcoded limitation. The TCLib-structure looks like this (first a short version without comments to give you a short overview - the full (documented) structure can be found below. STRUCTURE TCLib_objectclass,TCLib_SIZEOF LONG liboc_nextclass LONG liboc_classtext LONG liboc_classid BYTE liboc_flags0 BYTE liboc_flags1 BYTE liboc_flags2 BYTE liboc_flags3 LONG liboc_objectnew LONG liboc_objectduplicate LONG liboc_objectedit LONG liboc_objectdraw LONG liboc_objectload LONG liboc_objectsave LONG liboc_objectaction LABEL liboc_SIZEOF With nextclass you can link different objectclasses. Thus you can put multiple objectclasses in one TCLib. Classtext & classid describe the objectclass (the first for the use (in ) and the latter for saving or macro-commands). Objectnew, objectduplicate and objectload are used for creating new instances of objects, objectedit allows the modification of this instance and objectsave stores this instance in a TurboCalc-sheet. Objectdraw asks the objectclass to render the specific instance to a given rastport (in a specified size). Now the detailed structure: STRUCTURE TCLib_objectclass,TCLib_SIZEOF LONG liboc_nextclass ; *next object-class (used by TC to keep list of all classes) ; should be set to 0.l ; (or to pointer on next object-class. This way you ; can store multiple classes in one tclib! Last class ; must have 0.l then!) LONG liboc_classtext ; *short_text (null-terminated), is object-description ; This text will be shown in the -Requester! LONG liboc_classid ; This field contains up to 4 chars with an id for this ; objectclass (thus it should be unique). It is used to ; select and define a specific objectclass (for loading/ ; saving or with the OBJECT-macro) ; If the text has less then 4 chars, fill it with \0s ; 'GEL\0', 'IFF\0', 'TEXT', 'CHRT' are used for the intern ; object-classes, 'LOGO' for the extern one. ; See MISSING. BYTE liboc_flags0 OBJCLASSFLAGS0_FRAME = 0 ; %00=off, %01=on, %10=3d, %11=3d-2 OBJCLASSFLAGS0_FRAME_3d = 1 OBJCLASSFLAGS0_BACKFILL = 2 ; enables backfill of object OBJCLASSFLAGS0_BACKWHITE = 3 ; backfill with white (instead of grey) BYTE liboc_flags1 OBJCLASSFLAGS1_EDITTASK = 0 ; call _objectedit from the task not the process OBJCLASSFLAGS1_ACTIONTASK = 1 ; dito for _objectaction (see tclib.doc) BYTE liboc_flags2 BYTE liboc_flags3 ; object-flags, if not defined below: reserved & set to 0 ; liboc_flag0: default-values for new object: LONG liboc_objectnew ; object, flags = objectnew(num1/num2/*text) ; d0 d1 d0 d1 a0 ; generate a new, empty object ; para: d0/d1/a0: number/number/*text ; Normally all three regs are set to 0.l, which asks ; for a default object. ; These paras are set by the macro-command OBJECT to ; allow the creation of a specific object. ; ; if called with paras, see macro OBJECT ; otherwise all three regs are 0, it would be a good ; idea to return 1 in d1 (to let the user ; configurate his object - if needed) ; return: d0: *object (or 0.l if not possible) ; d1: auto_edit (0=no, 1=call OBJECT_EDIT ; after initialization - if called with default ; paras 0/0/0 the a good idea to return d1=1 ; (and thus let the user configurate this object, ; if possible) ; ATTENTION: d0 is used by TC to identify the object ; (of all classes), so d0 should be unique for all classes. ; Thus return a pointer to allocated mem (either with ; exec's or TC's routine!) LONG liboc_objectduplicate ; object = duplicate(object) ; d0 a0 ; Duplicate the object a0 return the new *object in d0 ; (or 0.l, if duplication failed) LONG liboc_objectedit ; redisplay = edit(object) ; d0 a0 ; 'edit' the object a0 - e.g. open a requesterto user-change ; object-settings ; para: a0=*object (a3=*sheet, a4=*tcobject, both private!!!) ; return: d0<>0: redisplay as something was changed! LONG liboc_objectdraw ; draw object a0 ; para: a0:*object ; a2: rp ; a6: *GfxBase (simply to make life easier ;^) ; d0-d3: object_box (x1/y1/x2/y2) ; d4: scale (for screen 0.l, ; for printer: lower_word = numerator ; upper_word = denominator ; 'scale' is intended for scaling fonts ; you might prefer to use object_box for that reason ; (e.g. for scaling pictures) ; can be used to scale fonts... ; newsize=oldsize*(d4&0xffff)/(d4>>16) ; or in asm (d0=oldsize) ; tst.l d4 ; beq.s noscale ; mulu d4,d0 ; swap d4 ; divu d4,d0 ; swap d4 ; noscale: ; ; d5: flags (currently unused: 0.l) LONG liboc_objectload ; Create new object by loading it from sheet. ; This is a bit tricky... ; para: d0=0 (or d0=1 & a0=*mem, see iii) ; (a2=*tcobject, a3=*sheet, a4=*load_handle) ; ; return: ; a0: *object ; d0: flags ; this allows the following tree possibilities: ; i) a0=*object, d0=0 (or d0=1, see iii) ; ii) a0=0.l, d0=0.l: error occured, no object created ; (e.g. no memory) ; iii) a0=0.l, d0=size ; When you return this, TurboCalc reads d0 bytes and ; calls this routine `loboc_objectload' again. ; Create your object from this memory then and ; return it in a0 (case i) ; If you return with a0=object & d0=0, TurboCalc frees ; the allocated memory for you (as TC allocated it) ; If you insist on freeing this piece of memory by your ; routine (e.g. it is exactly your private object- ; structure), then return with d0=1. ; (Remark: This mem is allocated with TC's AllocMemClear! ; your OBJECT_FREE-routine thus must free this mem ; with TC's FreeMem.) LONG liboc_objectsave ; When TurboCalc saves a sheet (with objects) this routine ; is called for every object. ; para: a0 = object ; d0 = flags, normally 0 (or 1, see iv)! ; (a2=*tcobject, a3=*sheet, a4=*save_handle) ; return: a0 = *block ; d0 = blocksize ; d1 = flags ; ; You have the following four possibilities: ; ; i) a0=*mem, d0=size, d1=0.l - don't free mem ; Save size bytes starting at mem, but to not free ; mem (usefull, if you simply return in a0 a pointer ; to your private structure - probably to be used ; with loading-case iii), d0=1 ) ; ii) a0=*mem, d0=size, d1=1.l ; Save size bytes starting at mem, and free Mem via ; TurboCalc's FreeMem-Routine - this piece of memory ; thus should be allocated via AllocMem(Clear) ; iii) a0=*mem, d0=size, d1=2.l - free mem via exec's ; Save size bytes starting at mem, and free Mem via ; exec's FreeMem-Routine: _LVOFreeMem(mem,size) ; iv) a0=0.l, d0=size - return size only ; You want to save the object yourself using ; Write_Byte/Word/Long/Size (see below) ; To do this, TurboCalc calls this routine again ; (with para d0=1) after saving the object-header. ; Important: TurboCalc *must* save the object-header ; first, therefore the size must be specified correctly ; 1) set a0=0 & d0=size, return (do *not* write ; in this mode) ; 2) your routine is called again with d0=1 ; Now write the size bytes with Write_... ; and return: a0=0.l, d0=0.l LONG liboc_objectaction ; This routine is called when clicking on the object ; para: d0=mode (0=click on object, 1=double-click) ; d1=flags (for clicking: 0=clicked on object (macro) ; 1=clicked on object (move) ; 2=clicked on 'size' ; bit7: if set: object_back (for 1/2) ; (for double-click: is 0.l up to now) ; a0=object ; ; return: d0=error (0=ok) ; for double-click: if you return with d0<>0 ; the default action (opening the settings- ; requester) isn't done, double-click will ; simple be aborted. This is usefull if you ; want to replace the default double-click-action. ; Return value is only used when OBJCLASSFLAGS1_ACTIONTASK ; is selected. Otherwise it is ignored (as the routine ; is called unsynchronously). ; ; Inportant: It is possible that (in future) new modes will be ; added. So please check for the current (implemented) modes ; and return d0=0 for the others (and do *not* rely on d0 ; being 1 if d0<>0!!!). ; ; You might do whatever you want (e.g. playing a sample ; for moving/sizing, starting an external program on double-click) ; IF your object has no 'special action' simply omit this ; routine (by setting this pointer to 0.l) ; LABEL liboc_SIZEOF Important: Some of these routines are called by TurboCalcs-Window task (which is used for the 'display'). Please note that it is not possible to call functions from the dos.library from a task (see dos.library for further information). These routines are called from the task: liboc_objectdraw (* see below) liboc_objectedit (**) liboc_objectaction (**) If you need the dos.library from within these routines, you may start a new process doing your stuff. Attention: As the task does the complete window management your routine should be very short! (*) liboc_objectdraw is called both from the task (for displaying the object on screen) and from the process (for printing). Thus the routine may be called twice (i.e. your routine should be reentrant or at least be callable twice) These two modes can be distinguished with the help of register d4 (scale) which is 0.l when called from the task and otherwise reflects the scale (and is <>0.l in all cases). Hint: This is useful for the following situation. If your objects uses fonts they should be loaded on new/duplicate/load/edit so the task can use them without using dos.library. If the drawing routine is called then with d4<>0 (i.e. from the process to render the object for printing) you can open a scaled and adapted font, use it and close it again before returning from the drawing routine. Important: When called with d4=0 you *must not* use any function with disk-access (i.e. most of the functions from dos.library and OpenDiskFont from diskfont.library!) (**) Those two routines are either called from the process or from the task. You can control that behavior with the two flags OBJCLASSFLAGS1_EDITTASK and OBJCLASSFLAGS1_ACTIONTASK defined above. If you do not set them, your routines are called from the process (asynchronously). This is the safer and easier way. If your routines are only short (without disk-access) and related to the actions very closely think of setting the respective flags (e.g. only this way you can cancel a double-click or response immediately to a mouse-click) 2.5. External Functions/Macro-Commands -------------------------------------- This kind of TCLib is used to add external functions or macro- commands to TurboCalc. These new routines can be accessed via TCFUNCTION and TCMACRO respectively. You may mix functions and macros within one tclib, so you can provide one TCLib for one topic containing both functions and macros. STRUCTURE TCLib_function,TCLib_SIZEOF LONG libfnc_flags ; reserved, unused, set to 0.l! LONG libfnc_count ; #routines below (routine0..routinecount-1) LONG libfnc_defaultroutine ; this routine is called if either d7 >=count or ; libfnc_routine(d7) is 0.l LONG libfnc_routine0 ; LONG libfnc_routine1 ; LONG libfnc_routine2 ; ... ; LONG libfnc_routine(count-1) LABEL libfnc_SIZEOF * parameters for all the fnc_routines: d0-d1: Value1 (as float) d2: Value1 (as long) d3-d4: Value2 (as float) d5: Value2 (as long) d7: routine-offset (0..) If libfnc_routinex is called, this is equal to x and thus not needed. If libfnc_defaulroutine is called you might need this data. a0: String (or 0.l) (must only be read not changed, will be freed by TurboCalc when your routine returns! Annotation: The two values are given both as float and as long. So you needn't convert them. 'Float' is the first one available in {mathieedoubbas/trans, mathieeesingbas/trans, mathffp/trans} (thus normally in double-ieee-format!). * return (for functions): d0/d1.l: data (type dependent) d2.l type - one of: TYPE_EMPTY = 0 ; no return value, shouldn't be used! TYPE_NO = 1 ; dito - please return NUM 0 instead (d0-d2 = 0/0/3) TYPE_FLOAT = 2 ; d0/d1.l is float as defined above TYPE_NUM = 3 ; d0.l is long TYPE_DATE = 4 ; d0.l is date (i.e. long) TYPE_TIME = 5 ; d0.l is date (i.e. long) TYPE_BOOL = 6 ; d0.l is bool (0=FALSE, 1=TRUE) TYPE_TEXT = 7 ; d0=*text (or 0, then is empty text!!!) ; texts *must* be allocted with AllocText, see ; calling conventions) TYPE_CELL = 8 ; d0.l=column/d1.l=row (you cannot return this in ; all situatuons) TYPE_ERROR = 9 ; d0.l=error (1..12) ; with 1=don't know, 2=DIV/0, 3=VERSION ; 4=REFERENCE, 5=)-BRACKET, 6=TYPE, 7=NOCELL ; 8=ARG_NO_RANGE, 9=(-BRACKET, 10=SEMICOLON ; 11=VALUE, 12=EOLINE * return (for macros): d0.l: error-code (0=ok, other see appendix of TurboCalc manual) Hint: As you cannot determine if a macro-command is called as functions it is a good idea to return the error code together with d2=TYPE_NUM (3). When called as macro, d2 is ignored, otherwise it is interpreted as normal value. 2.6. Calling Conventions ------------------------ There are some important things about calling your routines from TurboCalc: * All Parameters are passed in registers (as usually in assembler). If you are using c, you need an assembler-routine pushing the parameters on stack, calling your c-routine and popping them again before returning. * Return Value(s) are returned in registers as well (normally d0) * You are free to change d0-d1/a0-a1 - all the other registers should be preserved * For C-Users (and other compiled languages): Either compile with the option 'long code' (not using a base register) or set this base register before entering your routine (e.g. get_a5) Finally assure that the parameters are passed correctly (from registers to stack), as mentioned above. Further hints could probably be found in the chapter 'creating libraries' within your compiler manual or RKM. * You are passed in A5 a global data/routine-pointer from TurboCalc. (for all routines). With that pointer you can access some useful data (e.g. pointer on libraries) and some useful routines. Data is accessed via 'move.w offset(A5)' for example, the routines may be called with 'jsr offset(A5)' or simply XSR/XMP (defined in tclib2.i) TurboCalc_Version = -4 ; current revision/version TurboCalc_Revision = -2 ; of TurboCalc (starting with 3.02, sorry) STRUCTURE MainData,0 LONG DosBase ; Important: Dos, Gfx & Intuitionbase will LONG GfxBase ; be set correctly (as TC needs them to work), LONG IntuitionBase ; but you can't rely on the other libbases. LONG LayersBase ; They may be zero, if these libs aren't LONG DiskFontBase ; currently available in the system (e.g. LONG WBBase ; workbench is closed or KS 1.3 for asl.library) LONG ASLBase LONG IFFParseBase LONG RexxBase LONG AmigaGuideBase LONG LocaleBase * LONG FirstWindow ; private LONG FirstSheet ; . not even think of touching them!!! LONG FirstFont ; . LONG FontList ; . LONG LocaleCatalog ; . LONG AmigaGuideHandle ; . LONG Screen ; private * LONG Com_DiskErrorAdr ; error-routine-adr for Read_ & Write_ see below! * some useful routines * each vector consits of 6 bytes (first two: jmp, then the address) * call them as you normally call libraries (see macros XSR & XMP above) * if not mentioned otherwise, only d0-d1/a0-a1 are changed! * XVECT AllocMem ; para: d0 = size, return d0=a0=*mem - flags set ; size is stored by TC & this piece of memory ; will be freed automatically by TC ; (when TC ends and it hasn't been freed yet) XVECT AllocMemClear ; dito, but memory is cleared XVECT FreeMem ; para: a0 = *mem, frees with AllocMem allocated ; memory. Size was stored by AllocMem XVECT DuplicateA0 ; para: a0 =*string (0-terminated mem) ; return: a0=*new piece of mem with the same text ; (allocated with AllocMem) ; changed: only a0 is changed! * the next tree memory-routines are used for storing small pieces of memory * they are used for cell-texts, function-texts, cell-information,... XVECT AllocTEXTMem ; para: d0.l = size, return d0=a0=*mem XVECT FreeTextMem ; para: a0.l = allocated mem (with AllocTEXTMem!) XVECT DuplicateTEXT ; para: a0= *string (0-terminated) ; return: a0=*mem (allocated with AllocTEXTMem) * XVECT GetTexta0 ; private XVECT GetTexta1 ; private XVECT GetTexta2 ; private XVECT UpperCaseD0 ; d0.b = UpperCase(d0.b) * XVECT DOS_SendMessage_stack ; private XVECT IDCMP_SendMessage_stack ; . XVECT CheckA4_Sheet_getsheet ; . do not use these routines!!! XVECT CheckA4_Diagram ; . XVECT CheckA3 ; . XVECT StartClip ; . XVECT EndClip ; . XVECT SetClip ; private * XVECT Call_CDX ; d0/d1=float1, d3/d4=float2, d7=cmd ; for cmd see list below! * 'get information'-routines (column/row start at 0 for first one!) * all these routines need parameter a3=*sheet! XVECT Column_GetEntry ; para: d0=column, return: a0=*column or 0.l XVECT Column_GetEntry_readonly ; dito, but no creation XVECT Row_GetEntry ; para: d0=row, return: a0=*row or 0.l XVECT Row_GetEntry_readonly ; dito, but no creation XVECT Cell_GetEntry ; para: d0/d1=column/row, return: a0=*cell or 0.l XVECT Cell_GetEntry_readonly ; dito, but no creation XVECT Cell_GetInt ; para: d0/d1=column/row ; return: d0=int, d2=TYPE_NUM(3.l) or d2=0 (error) XVECT Cell_GetFloat ; para: d0/d1=column/row ; return: d0/d1=float, d2=TYPE_FLOAT(2.l) or d2=0 (error) XVECT Cell_GetText ; para: d0/d1=column/row ; return: a0=*text (allocated with AllocMemClear) ; or 0.l for error! ; (everything will be converted to text!!!) * loading/saving-routines. *_Open-Routines change a4 as a private file-handle (containing a buffer,...) * All other routines need this handle in a4 * Error handling: Except for _Open (and close, where no error can occur) * the reading/writing routines jump to the adress 'DiskErrorAdr', if * an error occurs. If you have stored the current stackpointer (a7) * when calling _Open, you can set it and close the file. * ..._Byte/Word/Long only change register d0, d1-d7/a0-a6 aren't touched! XVECT Read_Open_noerror ; d0=0:ok, else error - a4=handle (is returned) XVECT Read_Close ; close file a4 XVECT Read_Byte ; d0.b = read byte from file a4 XVECT Read_Word ; d0.w XVECT Read_Long ; d0.l XVECT Read_Size ; read d0.l bytes to a0.l from file a4 XVECT Read_TestEOF ; d0=0: eof, else not * XVECT Write_Open ; d0=0:ok, else error - a4=handle (is returned) XVECT Write_Close ; close file a4 XVECT Write_Byte ; write byte d0.b to file a4 XVECT Write_Word ; write word d0.w to file a4 XVECT Write_Long ; write long d0.l to file a4 XVECT Write_Size ; write d0.l bytes from a0.l to file a4 * drawing routines, for all: a2=rp, a6=gfxbase (has to be set!) XVECT XSetAPen ; d0=color XVECT XSetAPen_color ; d0=color XVECT XSetBPen ; d0=color XVECT XSetBPen_color ; d0=color XVECT XDrawLine ; d0-d3=x1/y1/x2/y2 3. Writing an own TCLib ======================== With this document and a bit programming experience it should be possible for you to write you own routines. 3.1 Examples ------------ There are two examples included to show how to create own TCLibs. Both examples are in assembler only (sorry), but feel free to make new examples in your favorite language (and send it to me to enlarge the examples, if you like to). The examples have been archived to 'Examples.Lha' due to lack of disk storage. 3.2 Problems & Suggestions -------------------------- If you have problems are some suggestions when writing your TCLib that can't be solved by this document and you have an email account you are free to contact me: s_friedr@ira.uka.de ukrc@rz.uni-karlsruhe.de But: * Read this document first, as this might already help you * I try to reply to all emails, but i can't guarantee that :) 3.3. New TCLib -------------- After you finished your TCLib. it would be very nice to send me a copy of your TCLib. First of all, I'm really interested whether there is some- one writing TCLibs and what kind of routines he's implementing. And then, if you agree, your TCLibs can be put onto the disk of the next version or be posted in some nets. In all cases, I will respect your copyright, so please note, whether your TCLib is in Public Domain (and I'm allowed/not allowed to put it on the TurboCalc-Disk) or if this is only a private copy for myself.